import axios, {
  AxiosInstance,
  InternalAxiosRequestConfig,
  AxiosRequestHeaders,
  AxiosResponse,
  AxiosError
} from 'axios'

import qs from 'qs'

import { config, resWhiteList } from './config'

import { ElMessage, ElMessageBox } from 'element-plus'

import { useBasicStoreWithOut } from '@/store/modules/basic'

import { useCache } from '@/hooks/web/useCache'

import { useTagsViewStore } from '@/store/modules/tagsView'

import { resetRouter } from '@/router'

const basicStore = useBasicStoreWithOut()

const { wsCache } = useCache()

const tagsViewStore = useTagsViewStore()

const { result_code } = config

export const PATH_URL = import.meta.env.VITE_API_BASEPATH || import.meta.env.VITE_BASE_PATH

declare module 'axios' {
  interface AxiosResponse<T = any> {
    configs: any
    // 这里追加你的参数
  }
  export function create(config?: AxiosRequestConfig): AxiosInstance
}

// 创建axios实例
const service: AxiosInstance = axios.create({
  baseURL: PATH_URL, // api 的 base_url
  timeout: config.request_timeout // 请求超时时间
})

// request拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    let query = {}
    const useQuery = config.data?._useQuery === false ? false : true
    try {
      if (config.data) {
        delete config.data._useQuery
      }
      const queryStr = (location.href.split('?')[1] || '').replace(/#\/\S*$/, '')
      query = qs.parse(queryStr)
    } catch (e) {}
    config.params = Object.assign(
      {},
      basicStore.getFirstQuery,
      useQuery ? query : {},
      config.params
    )
    if (
      config.method === 'post' &&
      (config.headers as AxiosRequestHeaders)['Content-Type'] ===
        'application/x-www-form-urlencoded'
    ) {
      config.data = qs.stringify(config.data)
    }
    ;(config.headers as AxiosRequestHeaders)['Token'] = wsCache.get('Admin-Token')
    ;(config.headers as AxiosRequestHeaders)['Authorization'] = wsCache.get('Admin-Token')
    // get参数编码
    if (config.method === 'get' && config.params) {
      let url = config.url as string
      url += url.includes('?') ? '&' : '?'
      const keys = Object.keys(config.params)
      for (const key of keys) {
        if (config.params[key] !== void 0 && config.params[key] !== null) {
          url += `${key}=${encodeURIComponent(config.params[key])}&`
        }
      }
      url = url.substring(0, url.length - 1)
      config.params = {}
      config.url = url
    }
    return config
  },
  (error: AxiosError) => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// response 拦截器
service.interceptors.response.use(
  (response: AxiosResponse<any>) => {
    console.log('=====', response.config.url)
    if (response.config.url && resWhiteList.includes(response.config.url)) {
      return response.data
    }
    if (response.config.responseType === 'blob') {
      // 如果是文件流，直接过
      return response
    } else if (
      response.data.error_code === 0 ||
      response.data.code === 0 ||
      (response.data.error_code || response.data.code) == result_code
    ) {
      return response.data
    } else if (
      [401, 403].includes(response.data.error_code || response.data.code) &&
      !response.config.url?.includes('/change_password') // 修改密码接口
    ) {
      ElMessageBox.confirm('登录失效，请重新登录?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        wsCache.clear()
        tagsViewStore.delAllViews()
        resetRouter() // 重置静态路由表
        // router.replace('/login')
        location.href = location.href.replace(/#\S+$/, '#/login')
      })
      return Promise.reject()
    } else {
      ElMessage({
        type: 'error',
        duration: 5000,
        showClose: true,
        message: `${response.data.error_msg || response.data.message}`
      })
      return Promise.reject()
    }
  },
  (error: any) => {
    console.log('err' + error) // for debug
    if (/\/getPermissions/.test(error?.config?.url)) {
      return Promise.reject(error)
    }
    ElMessage({
      type: 'error',
      duration: 5000,
      showClose: true,
      message: error.message
    })
    return Promise.reject(error)
  }
)

export { service }

export default service
